package com.capgemini.cn.authority.rest.resource;

import com.capgemini.cn.authority.rest.exception.AuthRestBusinessException;
import com.capgemini.cn.authority.rest.exception.IntegrityConstraintException;
import com.capgemini.cn.authority.rest.service.GroupService;
import com.capgemini.cn.authority.rest.service.PermissionService;
import com.capgemini.cn.authority.rest.service.RoleService;
import com.capgemini.cn.authority.rest.valueobject.DataResponse;
import com.capgemini.cn.authority.rest.valueobject.DataStatus;
import com.capgemini.cn.authority.rest.valueobject.data.GroupVO;
import com.capgemini.cn.authority.rest.valueobject.data.PermissionVO;
import com.capgemini.cn.authority.rest.valueobject.data.RoleVO;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created at 2017/9/21
 *
 * @author Andriy
 */
@RestController
@RequestMapping(path = BaseResource.RESOURCE_PREFIX + "role")
public class RoleResource extends BaseResource<RoleVO> {

    @Autowired
    private RoleService roleService;

    @Autowired
    private GroupService groupService;

    @Autowired
    private PermissionService permissionService;

    @ApiOperation(value = "查询单个角色详情")
    @Override
    public DataResponse<RoleVO> findByOne(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) {
        return this.roleService.findById(id).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "查询所有角色信息")
    @Override
    public DataResponse<List<RoleVO>> findAll(@ApiParam(value = PAGE_PARAM_COMMENT, name = PAGE_PARAM, required = true) @RequestParam(value = PAGE_PARAM) int page,
                                              @ApiParam(value = SIZE_PARAM_COMMENT, name = SIZE_PARAM, required = true) @RequestParam(value = SIZE_PARAM) int size,
                                              @ApiParam(value = ORDER_PARAM_COMMENT, name = ORDER_PARAM, required = true) @RequestParam(value = ORDER_PARAM) String order,
                                              @ApiParam(value = DIRECTION_PARAM_COMMENT, name = DIRECTION_PARAM, required = true) @RequestParam(value = DIRECTION_PARAM) Sort.Direction direction) {
        return this.roleService.findAll(page, size, order, direction).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "根据条件查询所有角色信息")
    public DataResponse<List<RoleVO>> findAll(@ApiParam(value = "角色名称，支持模糊查询", name = "roleName", required = true) @RequestParam(value = "roleName") String roleName,
                                              @ApiParam(value = PAGE_PARAM_COMMENT, name = PAGE_PARAM, required = true) @RequestParam(value = PAGE_PARAM) int page,
                                              @ApiParam(value = SIZE_PARAM_COMMENT, name = SIZE_PARAM, required = true) @RequestParam(value = SIZE_PARAM) int size,
                                              @ApiParam(value = ORDER_PARAM_COMMENT, name = ORDER_PARAM, required = true) @RequestParam(value = ORDER_PARAM) String order,
                                              @ApiParam(value = DIRECTION_PARAM_COMMENT, name = DIRECTION_PARAM, required = true) @RequestParam(value = DIRECTION_PARAM) Sort.Direction direction) {
        return this.roleService.findAll(roleName, page, size, order, direction).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "删除单个角色")
    @Override
    public DataResponse remove(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) throws AuthRestBusinessException {
        try {
            if (!this.roleService.delete(id)) throw new AuthRestBusinessException("删除主键ID值为" + id + "的角色实体对象时操作失败！");
        } catch (IntegrityConstraintException e) {
            throw new AuthRestBusinessException("必须先解除当前角色与用户组的关系才能进行删除。");
        }
        return new DataResponse(DataStatus.SUCCESS, "");
    }

    @ApiOperation(value = "新增角色")
    @PostMapping(path = "add")
    public DataResponse<RoleVO> add(@ApiParam(value = "角色名称", name = "name", required = true) @RequestParam(name = "name") String name) {
        return this.roleService.add(new RoleVO(name)).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "更新指定角色")
    @PutMapping(path = "update/{id}")
    public DataResponse<RoleVO> update(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id,
                                       @ApiParam(value = "需要更新的属性列表，key为字符串类型用以标识需要更新的属性名称，value为对象类型用以存放更新后的数据值，例如：{\"name\":\"value\"}", name = "properties", required = true) @RequestParam(name = "properties") List<String> properties) throws AuthRestBusinessException, IOException {
        Map<String, Object> propMaps = new HashMap<>();
        ObjectMapper objectMapper = new ObjectMapper();
        for (String propData : properties) propMaps.putAll(objectMapper.readValue(propData, Map.class));
        return this.roleService.update(id, propMaps).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "查询当前角色被分配到的用户组列表信息")
    @GetMapping(value = "member/{id}")
    public DataResponse<List<GroupVO>> findAllGroups(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id) {
        return this.groupService.findGroupByRole(id).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "查询角色所拥有的权限数据")
    @GetMapping(value = "permission/{id}")
    public DataResponse<List<PermissionVO>> findPermissionRole(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(value = ID_PARAM) long id) {
        return this.permissionService.findPermissionByRole(id).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "为角色批量分配指定权限，返回角色最新的权限绑定信息数据")
    @PostMapping(value = "assign/{id}")
    public DataResponse<List<PermissionVO>> assignRole(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id,
                                                       @ApiParam(value = "需要分配的权限数据主键ID值，组成JSON数组的形式传递", name = "permissionIds", required = true) @RequestParam(name = "permissionIds") Long... permissionIds) {
        return this.permissionService.assignPermission(id, permissionIds).setDataStatus(DataStatus.SUCCESS);
    }

    @ApiOperation(value = "为角色批量解绑指定权限，返回角色最新的权限绑定信息数据")
    @DeleteMapping(value = "release/{id}")
    public DataResponse<List<PermissionVO>> releaseRole(@ApiParam(value = ID_PARAM_COMMENT, name = ID_PARAM, required = true) @PathVariable(name = ID_PARAM) long id,
                                                        @ApiParam(value = "需要解绑的权限数据主键ID值，组成JSON数组的形式传递", name = "permissionIds", required = true) @RequestParam(name = "permissionIds") Long... permissionIds) {
        return this.permissionService.releasePermission(id, permissionIds).setDataStatus(DataStatus.SUCCESS);
    }
}
